//
// Created by zhouwd on 2019/7/12.
//
#include <jni.h>
#include <android/asset_manager_jni.h>
#include "media_player.h"
#include "media_render.h"
#include "media_video_frame_notify.h"
#include "media_init_notify.h"
#include "media_audio_frame_notify.h"

MediaPlayer *mediaPlayer;
MediaVideoFrameNotify *mediaVideoFrameNotify;
MediaInitNotify *mediaInitNotify;
MediaAudioFrameNotify *mediaAudioFrameNotify;

extern "C"
char * getShaderFromAsset(AAssetManager* mgr, const char *mfile) {
    AAsset* assetFragmentShader = AAssetManager_open(mgr, mfile, AASSET_MODE_UNKNOWN);

    if(assetFragmentShader==NULL)
    {
        ALOGE(" %s","asset==NULL");
        return NULL;
    }
    /*获取文件大小*/
    off_t bufferSize = AAsset_getLength(assetFragmentShader);
    //ALOGE("file size : %d\n",bufferSize);
    char *buffer=(char *)malloc(bufferSize+1);
    buffer[bufferSize]=0;
    int numBytesRead = AAsset_read(assetFragmentShader, buffer, bufferSize);
    ALOGE("numBytesRead: %d",numBytesRead);
    ALOGE("buffer: %s",buffer);

    /*关闭文件*/
    AAsset_close(assetFragmentShader);

    return buffer;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_zhouwd_zplayer_JniUtil_init(JNIEnv *env, jclass type, jstring filePath_, jobject assetManager) {
    const char *filePath = env->GetStringUTFChars(filePath_, 0);


    AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);

    if(mgr==NULL)
    {
        ALOGE(" %s","AAssetManager==NULL");
        return JNI_FALSE;
    }

    const char *mPreviewFragmentShaderFile = "preview_fragment_shader.glsl";
    const char *mPreviewVertexShaderFile = "preview_vertex_shader.glsl";

    char *mPreviewFragmentShaderBuffer = getShaderFromAsset(mgr, mPreviewFragmentShaderFile);
    char *mPreviewVertexShaderBuffer = getShaderFromAsset(mgr, mPreviewVertexShaderFile);

    // TODO
    mediaPlayer = new MediaPlayer();
    mediaPlayer->init(filePath, mPreviewVertexShaderBuffer, mPreviewFragmentShaderBuffer);

    free(mPreviewVertexShaderBuffer);
    free(mPreviewFragmentShaderBuffer);

    env->ReleaseStringUTFChars(filePath_, filePath);

    return JNI_FALSE;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_zhouwd_zplayer_JniUtil_start(JNIEnv *env, jclass type) {

    // TODO
    mediaPlayer->start();

    return JNI_FALSE;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_zhouwd_zplayer_JniUtil_pause(JNIEnv *env, jclass type) {

    // TODO
    mediaPlayer->pause();
    return JNI_TRUE;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_zhouwd_zplayer_JniUtil_stop(JNIEnv *env, jclass type) {

    // TODO
    mediaPlayer->stop();
    return JNI_TRUE;
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_zhouwd_zplayer_JniUtil_release(JNIEnv *env, jclass type) {

    // TODO
    mediaPlayer->release();

    delete mediaPlayer;

    return JNI_TRUE;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhouwd_zplayer_JniUtil_step(JNIEnv *env, jclass type) {

    // TODO
    return mediaPlayer->step();
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhouwd_zplayer_JniUtil_resize(JNIEnv *env, jclass type) {

    // TODO

    return mediaPlayer->resize();
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhouwd_zplayer_JniUtil_initVideoFrameNotify(JNIEnv *env, jclass type, jobject videoFrameNotify) {

    // TODO
    if (mediaVideoFrameNotify == nullptr) {
        mediaVideoFrameNotify = new MediaVideoFrameNotify();
    }
    mediaPlayer->setMediaVideoFrameNotify(mediaVideoFrameNotify);

    jclass objClass = env->GetObjectClass(videoFrameNotify);
    JavaVM *javaVM;

    jint getJavaVmResult = env->GetJavaVM(&javaVM);

    ALOGE("initVideoFrameNotify > getJavaVmResult > %d", getJavaVmResult );

    jobject callbackObj = env->NewGlobalRef(videoFrameNotify);

    if(callbackObj == NULL)
    {
        ALOGE("Error NewGlobalRef");
    }

    jmethodID onChangedMD = env->GetMethodID(objClass, "notifyUpdateVideoFrame", "()V");

    if(onChangedMD == NULL)
    {
        ALOGE("Error GetMethodID");
    }
    //env->CallVoidMethod(callbackObj, onChangedMD);
    mediaVideoFrameNotify->init(javaVM, callbackObj, onChangedMD);
    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhouwd_zplayer_JniUtil_destoryVideoFrameNotify(JNIEnv *env, jclass type) {

    mediaVideoFrameNotify->destory();
    delete mediaVideoFrameNotify;
    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhouwd_zplayer_JniUtil_initAudioFrameNotify(JNIEnv *env, jclass type, jobject jAudioFrameNotify) {

    if (mediaAudioFrameNotify == nullptr) {
        mediaAudioFrameNotify = new MediaAudioFrameNotify();
    }

    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_zhouwd_zplayer_JniUtil_initMediaInitNotify(JNIEnv *env, jclass type, jobject jMediaInitNotify) {

    if (mediaInitNotify == nullptr) {
        mediaInitNotify = new MediaInitNotify();
    }

    jclass objClass = env->GetObjectClass(jMediaInitNotify);
    JavaVM *javaVM;

    jint getJavaVmResult = env->GetJavaVM(&javaVM);

    ALOGE("initVideoFrameNotify > getJavaVmResult > %d", getJavaVmResult );

    jobject callbackObj = env->NewGlobalRef(jMediaInitNotify);

    if(callbackObj == NULL)
    {
        ALOGE("Error NewGlobalRef");
    }

    jmethodID onChangedMD = env->GetMethodID(objClass, "notifyMediaInit", "(IIIII)V");

    if(onChangedMD == NULL)
    {
        ALOGE("Error GetMethodID");
    }
    mediaInitNotify->init(javaVM, callbackObj, onChangedMD);
    return 0;
}